package com.dd.cloud.user.service.patient.impl;

import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.dd.cloud.common.constants.UserConstants;
import com.dd.cloud.common.exception.ZekeException;
import com.dd.cloud.common.interceptor.UserInterceptor;
import com.dd.cloud.common.vo.LoginInfo;
import com.dd.cloud.common.vo.PageReq;
import com.dd.cloud.user.entity.doctor.PatientDeliveryAddr;
import com.dd.cloud.user.entity.patient.PatientAddressLink;
import com.dd.cloud.user.entity.patient.PatientUserAddress;
import com.dd.cloud.user.mapper.doctor.PatientDeliveryAddrMapper;
import com.dd.cloud.user.mapper.patient.PatientMedRankMapper;
import com.dd.cloud.user.mapper.patient.PatientUserAddressMapper;
import com.dd.cloud.user.req.patient.PatientUserAddressReq;
import com.dd.cloud.user.req.patient.PatientUserAddressUpdate;
import com.dd.cloud.user.res.patient.PatientMedCardBindRes;
import com.dd.cloud.user.service.doctor.IPatientDeliveryAddrService;
import com.dd.cloud.user.service.patient.IPatientAddressLinkService;
import com.dd.cloud.user.service.patient.IPatientMedRankService;
import com.dd.cloud.user.service.patient.IPatientUserAddressService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 * 用户患者地址 服务实现类
 * </p>
 *
 * @author czg
 * @since 2023-07-18
 */
@Service
@Slf4j
public class PatientUserAddressServiceImpl extends ServiceImpl<PatientUserAddressMapper, PatientUserAddress> implements IPatientUserAddressService {

    @Autowired
    private PatientMedRankMapper patientMedRankMapper;
    @Autowired
    private IPatientDeliveryAddrService patientDeliveryAddrService;

    @Autowired
    private IPatientAddressLinkService patientAddressLinkService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void addUserAddress(PatientUserAddressReq patientUserAddressReq) {
        LoginInfo loginInfo = UserInterceptor.getLoginUserInfo(LoginInfo.UserType.PATIENT).get();
        Integer userId = loginInfo.getId();
        PatientUserAddress patientUserAddress = new PatientUserAddress();
        BeanUtils.copyProperties(patientUserAddressReq, patientUserAddress);
        checkUserAddress(patientUserAddress, userId);
        LocalDateTime createDate = LocalDateTime.now();
        patientUserAddress.setCreateDate(createDate);
        patientUserAddress.setUserId(userId);
        patientUserAddress.setStatus(1);
        boolean flag = this.save(patientUserAddress);
        if (!flag) {
            throw new ZekeException("保存用户地址失败");
        }
        //查询用户的就诊人列表
        List<PatientMedCardBindRes> medList = patientMedRankMapper.bindMedList(userId);
        if (CollectionUtil.isNotEmpty(medList)) {
            List<PatientAddressLink> bindAddressLink = new ArrayList<>();
            Integer userAddressId = patientUserAddress.getId();
            log.info("用户地址id:{}", userAddressId);
            List<String> reslist = medList.stream().map(PatientMedCardBindRes::getMedId).collect(Collectors.toList());
            log.info("所有就诊人medIds:{}", reslist);
            for (String medId : reslist) {
                log.info("就诊人medId:{}", medId);
                PatientDeliveryAddr medAddress = new PatientDeliveryAddr();
                medAddress.setMedId(medId)
                        .setStatus(1)
                        .setType(0)
                        .setCreateDate(createDate)
                        .setAddr(patientUserAddress.getAddr())
                        .setDistrict(patientUserAddress.getDistrict())
                        .setProvince(patientUserAddress.getProvince())
                        .setCity(patientUserAddress.getCity())
                        .setMobileNumber(patientUserAddress.getMobileNumber())
                        .setReceiver(patientUserAddress.getReceiver());
                boolean flag2 = patientDeliveryAddrService.save(medAddress);
                if (!flag2) {
                    throw new ZekeException("保存就诊人地址失败");
                }
                Integer medAddressId = medAddress.getId();
                log.info("地址id:{}", medAddressId);
                PatientAddressLink patientAddressLink = new PatientAddressLink();
                patientAddressLink.setUserAddressId(userAddressId)
                        .setMedAddressId(medAddressId)
                        .setStatus(1);
                bindAddressLink.add(patientAddressLink);
            }
            if (CollectionUtil.isNotEmpty(bindAddressLink)) {
                patientAddressLinkService.saveBatch(bindAddressLink);
            }
        }
    }

    private void checkUserAddress(PatientUserAddress req, Integer userId) {
        LambdaQueryWrapper<PatientUserAddress> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(PatientUserAddress::getUserId, userId)
                .eq(PatientUserAddress::getStatus, UserConstants.DeliveryAddrStatus.NORMAL);
        if (req.getId() != null) {
            queryWrapper.ne(PatientUserAddress::getId,req.getId());
        }
        List<PatientUserAddress> addrList = list(queryWrapper);
        if (CollectionUtils.isNotEmpty(addrList)) {
            String reqReceiver = req.getReceiver();
            String reqMobileNumber = req.getMobileNumber();
            String reqAddr = req.getAddr();
            String reqProvince = req.getProvince();
            String reqCity = req.getCity();
            String reqDistrict = req.getDistrict();
            String newStr = reqReceiver + reqMobileNumber + reqProvince + reqCity + reqDistrict + reqAddr;
            newStr = newStr.trim();
            for (PatientUserAddress patientDeliveryAddr : addrList) {
                String receiver = patientDeliveryAddr.getReceiver();
                String mobileNumber = patientDeliveryAddr.getMobileNumber();
                String addr = patientDeliveryAddr.getAddr();
                String province = patientDeliveryAddr.getProvince();
                String city = patientDeliveryAddr.getCity();
                String district = patientDeliveryAddr.getDistrict();
                String oldStr = receiver + mobileNumber + province + city + district + addr;
                oldStr = oldStr.trim();
                if (newStr.equals(oldStr)) {
                    throw new ZekeException("请勿重复添加地址!");
                }
            }
        }
    }

    /**
     * 编辑用户地址
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateUserAddress(PatientUserAddressUpdate patientUserAddressUpdate) {
        Integer addressId = patientUserAddressUpdate.getId();
        PatientUserAddress patientUserAddress = this.getById(addressId);
        if (patientUserAddress == null) {
            throw new ZekeException("记录不存在");
        }
        BeanUtils.copyProperties(patientUserAddressUpdate, patientUserAddress);
        checkUserAddress(patientUserAddress, patientUserAddress.getUserId());
        this.updateById(patientUserAddress);
        //查询这个用户地址关联的就诊地址、
        LambdaQueryWrapper<PatientAddressLink> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(PatientAddressLink::getUserAddressId, patientUserAddress.getId())
                .eq(PatientAddressLink::getStatus, 1);
        List<PatientAddressLink> patientAddressLinks = patientAddressLinkService.getBaseMapper().selectList(wrapper);
        if (CollectionUtil.isNotEmpty(patientAddressLinks)) {
            List<Integer> medAddressIds = patientAddressLinks.stream().map(PatientAddressLink::getMedAddressId).collect(Collectors.toList());
            for (Integer medAddressId : medAddressIds) {
                PatientDeliveryAddr patientDeliveryAddr = new PatientDeliveryAddr();
                patientDeliveryAddr.setId(medAddressId)
                        .setReceiver(patientUserAddress.getReceiver())
                        .setMobileNumber(patientUserAddress.getMobileNumber())
                        .setProvince(patientUserAddress.getProvince())
                        .setCity(patientUserAddress.getCity())
                        .setDistrict(patientUserAddress.getDistrict())
                        .setAddr(patientUserAddress.getAddr());
                patientDeliveryAddrService.updateById(patientDeliveryAddr);
            }
        }
    }

    /**
     * 查询用户地址列表
     */
    @Override
    public IPage<PatientUserAddress> queryUserAddressPage(PageReq pageReq) {
        LoginInfo loginInfo = UserInterceptor.getLoginUserInfo(LoginInfo.UserType.PATIENT).get();
        Integer userId = loginInfo.getId();
        LambdaQueryWrapper<PatientUserAddress> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(PatientUserAddress::getUserId, userId)
                .eq(PatientUserAddress::getStatus, 1)
                .orderByDesc(PatientUserAddress::getCreateDate);
        IPage<PatientUserAddress> patientUserAddresses = this.page(pageReq.pagePojo(), wrapper);
        return patientUserAddresses;
    }

    /**
     * 删除地址
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void updatePatientUserAddress(Integer id) {
        LambdaUpdateWrapper<PatientUserAddress> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.set(PatientUserAddress::getStatus, -1)
                .eq(PatientUserAddress::getId, id);
        boolean flag = this.update(updateWrapper);
        if (!flag) {
            throw new ZekeException("删除地址失败");
        }
        //删除就诊人地址
        LambdaQueryWrapper<PatientAddressLink> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(PatientAddressLink::getUserAddressId, id)
                .eq(PatientAddressLink::getStatus, 1);
        List<PatientAddressLink> patientAddressLinks = patientAddressLinkService.list(queryWrapper);
        if (CollectionUtil.isNotEmpty(patientAddressLinks)) {
            List<Integer> medAddressIds = patientAddressLinks.stream().map(PatientAddressLink::getMedAddressId).collect(Collectors.toList());
            LambdaUpdateWrapper<PatientDeliveryAddr> lambdaUpdateWrapper = new LambdaUpdateWrapper<>();
            lambdaUpdateWrapper.set(PatientDeliveryAddr::getStatus, -1)
                    .in(PatientDeliveryAddr::getId, medAddressIds);
            boolean flag2 = patientDeliveryAddrService.update(lambdaUpdateWrapper);
            if (!flag2) {
                throw new ZekeException("删除地址失败");
            }
            //删除关联关系
            LambdaUpdateWrapper<PatientAddressLink> patientAddressLinkLambdaUpdateWrapper = new LambdaUpdateWrapper<>();
            patientAddressLinkLambdaUpdateWrapper.eq(PatientAddressLink::getUserAddressId, id)
                    .set(PatientAddressLink::getStatus, -1);
            boolean flag3 = patientAddressLinkService.update(patientAddressLinkLambdaUpdateWrapper);
            if (!flag3) {
                throw new ZekeException("删除地址失败");
            }
        }
    }
}
